// +build !windows

package laxexec

import (
    "os"
    "os/exec"
    "os/user"
    "strconv"
    "syscall"
)


// @Desc: 设置进程属性
// @param cmd
func setupCmd(cmd *exec.Cmd) {
    cmd.SysProcAttr = &syscall.SysProcAttr{}
    cmd.SysProcAttr.Setsid = true
}

// @Desc: 创建一个laxcommand
// @param cmd 指令整串
// @return *LaxCommand
func NewLaxCommand(cmd string) *LaxCommand {
    r := &LaxCommand{
        Cmd: exec.Command("/bin/bash", "-c", cmd),
    }
    setupCmd(r.Cmd)
    return r
}

// @Desc: 附带参数的指令
// @param name 指令名，比如cmd, dir, xx.exe
// @param args 启动参数
// @return *LaxCommand
func NewLaxCommandWithArgs(name string, args ...string) *LaxCommand {
    r := &LaxCommand{
        Cmd: exec.Command(name, args...),
    }
    setupCmd(r.Cmd)
    return r
}

// @Desc: 杀进程
// @param sig 杀进程信号,在windows上没有用
// @return error 杀进程结果
func (lc *LaxCommand) Terminate(sig os.Signal) error {
    if lc.Process == nil {
        return nil
    }
    // find pgid, ref: http://unix.stackexchange.com/questions/14815/process-descendants
    group, err := os.FindProcess(-1 * lc.Process.Pid)
    if err == nil {
        err = group.Signal(sig)
    }
    return err
}

// Ref: http://stackoverflow.com/questions/21705950/running-external-commands-through-os-exec-under-another-user
// @Desc: 设置用户
// @param name
// @return err
func (lc *LaxCommand) SetUser(name string) (err error) {
    u, err := user.Lookup(name)
    if err != nil {
        return err
    }
    uid, err := strconv.Atoi(u.Uid)
    if err != nil {
        return err
    }
    gid, err := strconv.Atoi(u.Gid)
    if err != nil {
        return err
    }
    if lc.SysProcAttr == nil {
        lc.SysProcAttr = &syscall.SysProcAttr{}
    }
    lc.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}
    return nil
}
